﻿using System;
using System.IO;
using System.Net;
using System.Text;

namespace ApiScanner.Core
{
    internal static class DavSearchHelper
    {
        private const string StoreEventUserAgent = "StoreEventFinder/0.1";

        internal static HttpWebRequest CreateWebRequest(Uri path, string requestBody)
        {
            var request = (HttpWebRequest) WebRequest.Create(path);

            var encoding = new ASCIIEncoding();
            byte[] requestBodyBytes = encoding.GetBytes(requestBody);

            // Set request method and headers
            request.AllowAutoRedirect = false;
            request.ContentLength = requestBodyBytes.Length;
            request.ContentType = "text/xml";
            request.KeepAlive = true;
            request.Method = "SEARCH";
            request.PreAuthenticate = false;
            request.ProtocolVersion = HttpVersion.Version10;
            request.UnsafeAuthenticatedConnectionSharing = true;
            request.UseDefaultCredentials = true;
            request.UserAgent = StoreEventUserAgent;
            request.Headers.Add("Brief: t"); // get rid of 404 Not Found on missing or null properties

            // Create request and set the body
            using (var bodyStream = request.GetRequestStream())
            {
                bodyStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);
            }


            return request;
        }

        internal static Stream DoSearch(Uri path, string requestBody)
        {
            var request = (HttpWebRequest) WebRequest.Create(path);

            var encoding = new ASCIIEncoding();
            byte[] requestBodyBytes = encoding.GetBytes(requestBody);

            // Set request method and headers
            request.AllowAutoRedirect = false;
            request.ContentLength = requestBodyBytes.Length;
            request.ContentType = "text/xml";
            request.KeepAlive = true;
            request.Method = "SEARCH";
            request.PreAuthenticate = false;
            request.ProtocolVersion = HttpVersion.Version10;
            request.UnsafeAuthenticatedConnectionSharing = true;
            request.UseDefaultCredentials = true;
            request.UserAgent = StoreEventUserAgent;
            request.Headers.Add("Brief: t"); // get rid of 404 Not Found on missing or null properties

            using (var bodyStream = request.GetRequestStream())
            {
                bodyStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);
            }

            var response = request.GetResponse();

            if (response.ContentType == "text/xml")
            {
                return response.GetResponseStream();
            }
            throw new InvalidOperationException("The response from the server is not text/xml.");
        }


        /// <summary>
        /// Builds WebDAV URL path to Exchange mailbox based on server and type of resource
        /// </summary>
        /// <param name="serverHostName">DNS hostname of server - OR - URL in case of MailboxType.ExplicitUri</param>
        /// <param name="mailbox">SMTP address of mailbox - optional for ExplicityUri</param>
        /// <param name="mailboxType">MailboxType</param>
        /// <returns>System.Uri to mailbox</returns>
        public static Uri BuildPath(
            string serverHostName,
            string mailbox,
            MailboxType mailboxType,
            bool useSSL,
            string domain)
        {
            const string exAdminPath = "/exadmin/admin/"; // For WebDAV admin logons only
            const string nonIpmSubtree = "/NON_IPM_SUBTREE/"; // The real root of the storage unit
            string mailboxRhs = null;
            string mailboxLhs = null;
            string prefix = useSSL ? "https://" : "http://";

            // split SMTP address into left-hand and right-hand sides
            if (mailbox != "")
            {
                mailboxRhs = mailbox.Substring(mailbox.IndexOf("@") + 1);
                mailboxLhs = mailbox.Substring(0, mailbox.IndexOf("@"));
            }

            switch (mailboxType)
            {
                case MailboxType.ExplicitUri:
                    // Just grab path passed and return it as a Uri
                    return new Uri(serverHostName);
                case MailboxType.PublicFolder:
                    // Use email address to get a valid domain
                    return new Uri(prefix + serverHostName + exAdminPath + domain + "/Public%20Folders/");
                case MailboxType.SystemPublicFolder:
                    return new Uri(prefix + serverHostName + exAdminPath + domain + "/Public%20Folders" + nonIpmSubtree);
                case MailboxType.SystemMailbox:
                    return
                        new Uri(prefix + serverHostName + exAdminPath + mailboxRhs + "/MBX/" + mailboxLhs +
                                nonIpmSubtree);
                case MailboxType.RegularMailbox:
                    return
                        new Uri(prefix + serverHostName + exAdminPath + mailboxRhs + "/MBX/" + mailboxLhs +
                                nonIpmSubtree);
                default:
                    return null;
            }
        }
    }
}